package ynu.edu.order.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import ynu.edu.common.exception.BusinessException;
import ynu.edu.common.result.Result;
import ynu.edu.order.client.DishClient;
import ynu.edu.order.client.MerchantClient;
import ynu.edu.order.client.UserClient;
import ynu.edu.order.dto.CreateOrderDTO;
import ynu.edu.order.dto.OrderDTO;
import ynu.edu.order.entity.Order;
import ynu.edu.order.entity.OrderItem;
import ynu.edu.order.repository.OrderItemRepository;
import ynu.edu.order.repository.OrderRepository;
import ynu.edu.order.service.OrderService;
import ynu.edu.order.vo.MerchantVO;
import ynu.edu.order.vo.OrderItemVO;
import ynu.edu.order.vo.OrderVO;
import ynu.edu.order.vo.UserVO;
import ynu.edu.order.vo.DishVO;
import ynu.edu.order.vo.DishSpecVO;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderRepository orderRepository;
    private final OrderItemRepository orderItemRepository;
    private final DishClient dishClient;
    private final MerchantClient merchantClient;
    private final UserClient userClient;

    /**
     * 创建订单
     * @param createOrderDTO 创建订单DTO
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderVO createOrder(CreateOrderDTO createOrderDTO) {
        // 1. 校验参数
        if (createOrderDTO.getUserId() == null) {
            throw new BusinessException("用户ID不能为空");
        }
        if (createOrderDTO.getMerchantId() == null) {
            throw new BusinessException("商家ID不能为空");
        }
        if (createOrderDTO.getDeliveryAddress() == null) {
            throw new BusinessException("配送地址不能为空");
        }
        if (createOrderDTO.getReceiverName() == null) {
            throw new BusinessException("收货人姓名不能为空");
        }
        if (createOrderDTO.getReceiverPhone() == null) {
            throw new BusinessException("收货人电话不能为空");
        }
        if (createOrderDTO.getOrderItems() == null || createOrderDTO.getOrderItems().isEmpty()) {
            throw new BusinessException("订单项不能为空");
        }

        // 验证用户ID是否存在
        Result<UserVO> userResult = userClient.getUserById(createOrderDTO.getUserId());
        if (!userResult.getCode().equals(200) || userResult.getData() == null) {
            throw new BusinessException("用户不存在");
        }

        // 验证商家ID是否存在
        Result<MerchantVO> merchantResult = merchantClient.getMerchantById(createOrderDTO.getMerchantId());
        if (!merchantResult.getCode().equals(200) || merchantResult.getData() == null) {
            throw new BusinessException("商家不存在");
        }

        // 2. 创建订单
        Order order = new Order();
        // 生成订单号，格式：年月日时分秒+6位随机数
        String orderNo = generateOrderNo();
        order.setOrderNo(orderNo);
        order.setUserId(createOrderDTO.getUserId());
        order.setMerchantId(createOrderDTO.getMerchantId());
        order.setDeliveryAddress(createOrderDTO.getDeliveryAddress());
        order.setReceiverName(createOrderDTO.getReceiverName());
        order.setReceiverPhone(createOrderDTO.getReceiverPhone());
        order.setRemark(createOrderDTO.getRemark());
        order.setStatus(0); // 待支付
        
        // 调用菜品服务获取菜品信息，包括价格等
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<OrderItem> orderItems = new ArrayList<>();
        
        for (CreateOrderDTO.CreateOrderItemDTO itemDTO : createOrderDTO.getOrderItems()) {
            OrderItem orderItem = new OrderItem();
            orderItem.setDishId(itemDTO.getDishId());
            
            // 调用菜品服务获取菜品信息
            Result<DishVO> dishResult = dishClient.getDishById(itemDTO.getDishId());
            if (!dishResult.getCode().equals(200) || dishResult.getData() == null) {
                throw new BusinessException("获取菜品信息失败");
            }
            
            DishVO dish = dishResult.getData();
            BigDecimal price;
            String dishName = dish.getName();
            
            // 如果有规格，则获取规格价格
            if (itemDTO.getDishSpecId() != null) {
                orderItem.setDishSpecId(itemDTO.getDishSpecId());
                Result<DishSpecVO> specResult = dishClient.getDishSpecById(itemDTO.getDishSpecId());
                if (!specResult.getCode().equals(200) || specResult.getData() == null) {
                    throw new BusinessException("获取菜品规格信息失败");
                }
                DishSpecVO spec = specResult.getData();
                price = spec.getPrice();
                orderItem.setDishSpecName(spec.getName());
            } else {
                // 如果没有规格，则使用菜品价格
                price = dish.getPrice();
                orderItem.setDishSpecId(null);
                orderItem.setDishSpecName(null);
            }
            
            orderItem.setPrice(price);
            orderItem.setQuantity(itemDTO.getQuantity());
            orderItem.setSubtotal(price.multiply(new BigDecimal(itemDTO.getQuantity())));
            orderItem.setDishName(dishName);
            
            totalAmount = totalAmount.add(orderItem.getSubtotal());
            orderItems.add(orderItem);
        }
        
        // 设置订单总金额和实付金额
        order.setTotalAmount(totalAmount);
        // 假设配送费为5元
        BigDecimal deliveryFee = new BigDecimal("5.00");
        order.setDeliveryFee(deliveryFee);
        order.setActualAmount(totalAmount.add(deliveryFee));
        
        // 3. 保存订单
        Order savedOrder = orderRepository.save(order);
        
        // 4. 保存订单项
        for (OrderItem orderItem : orderItems) {
            orderItem.setOrderId(savedOrder.getId());
            orderItemRepository.save(orderItem);
        }
        
        // 5. 返回订单信息
        return convertToOrderVO(savedOrder, orderItems);
    }

    /**
     * 根据订单ID查询订单
     * @param id 订单ID
     * @return 订单信息
     */
    @Override
    public OrderVO getOrderById(Long id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(id, 0);
        return convertToOrderVO(order, orderItems);
    }

    /**
     * 根据订单号查询订单
     * @param orderNo 订单号
     * @return 订单信息
     */
    @Override
    public OrderVO getOrderByOrderNo(String orderNo) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
        return convertToOrderVO(order, orderItems);
    }

    /**
     * 根据用户ID查询订单列表
     * @param userId 用户ID
     * @param pageable 分页参数
     * @return 订单分页列表
     */
    @Override
    public Page<OrderVO> getOrdersByUserId(Long userId, Pageable pageable) {
        Page<Order> orderPage = orderRepository.findByUserIdAndIsDeleted(userId, 0, pageable);
        List<OrderVO> orderVOList = new ArrayList<>();
        
        for (Order order : orderPage.getContent()) {
            List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
            orderVOList.add(convertToOrderVO(order, orderItems));
        }
        
        return new PageImpl<>(orderVOList, pageable, orderPage.getTotalElements());
    }

    /**
     * 根据商家ID查询订单列表
     * @param merchantId 商家ID
     * @param pageable 分页参数
     * @return 订单分页列表
     */
    @Override
    public Page<OrderVO> getOrdersByMerchantId(Long merchantId, Pageable pageable) {
        // 获取当前请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String tokenType = (String) request.getAttribute("tokenType");
        
        // 验证是否是商家token
        if (!"merchant".equals(tokenType)) {
            throw new BusinessException("无权限访问，请使用商家账号登录");
        }
        
        // 验证商家ID是否匹配
        Long tokenMerchantId = (Long) request.getAttribute("merchantId");
        if (!merchantId.equals(tokenMerchantId)) {
            throw new BusinessException("无权查看其他商家的订单");
        }
        
        Page<Order> orderPage = orderRepository.findByMerchantIdAndIsDeleted(merchantId, 0, pageable);
        List<OrderVO> orderVOList = new ArrayList<>();
        
        for (Order order : orderPage.getContent()) {
            List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
            orderVOList.add(convertToOrderVO(order, orderItems));
        }
        
        return new PageImpl<>(orderVOList, pageable, orderPage.getTotalElements());
    }

    /**
     * 根据订单状态查询订单列表
     * @param status 订单状态
     * @param pageable 分页参数
     * @return 订单分页列表
     */
    @Override
    public Page<OrderVO> getOrdersByStatus(Integer status, Pageable pageable) {
        Page<Order> orderPage = orderRepository.findByStatusAndIsDeleted(status, 0, pageable);
        List<OrderVO> orderVOList = new ArrayList<>();
        
        for (Order order : orderPage.getContent()) {
            List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
            orderVOList.add(convertToOrderVO(order, orderItems));
        }
        
        return new PageImpl<>(orderVOList, pageable, orderPage.getTotalElements());
    }

    /**
     * 根据用户ID和订单状态查询订单列表
     * @param userId 用户ID
     * @param status 订单状态
     * @return 订单列表
     */
    @Override
    public List<OrderVO> getOrdersByUserIdAndStatus(Long userId, Integer status) {
        List<Order> orders = orderRepository.findByUserIdAndStatusAndIsDeleted(userId, status, 0);
        List<OrderVO> orderVOList = new ArrayList<>();
        
        for (Order order : orders) {
            List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
            orderVOList.add(convertToOrderVO(order, orderItems));
        }
        
        return orderVOList;
    }

    /**
     * 根据商家ID和订单状态查询订单列表
     * @param merchantId 商家ID
     * @param status 订单状态
     * @return 订单列表
     */
    @Override
    public List<OrderVO> getOrdersByMerchantIdAndStatus(Long merchantId, Integer status) {
        // 获取当前请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String tokenType = (String) request.getAttribute("tokenType");
        
        // 验证是否是商家token
        if (!"merchant".equals(tokenType)) {
            throw new BusinessException("无权限访问，请使用商家账号登录");
        }
        
        // 验证商家ID是否匹配
        Long tokenMerchantId = (Long) request.getAttribute("merchantId");
        if (!merchantId.equals(tokenMerchantId)) {
            throw new BusinessException("无权查看其他商家的订单");
        }
        
        List<Order> orders = orderRepository.findByMerchantIdAndStatusAndIsDeleted(merchantId, status, 0);
        List<OrderVO> orderVOList = new ArrayList<>();
        
        for (Order order : orders) {
            List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(order.getId(), 0);
            orderVOList.add(convertToOrderVO(order, orderItems));
        }
        
        return orderVOList;
    }

    /**
     * 支付订单
     * @param orderNo 订单号
     * @param payMethod 支付方式
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderVO payOrder(String orderNo, Integer payMethod) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        
        if (order.getStatus() != 0) {
            throw new BusinessException("订单状态不正确，无法支付");
        }
        
        order.setStatus(1); // 已支付待接单
        order.setPayMethod(payMethod);
        order.setPayTime(LocalDateTime.now());
        
        Order savedOrder = orderRepository.save(order);
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(savedOrder.getId(), 0);
        
        return convertToOrderVO(savedOrder, orderItems);
    }

    /**
     * 商家接单
     * @param orderNo 订单号
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderVO acceptOrder(String orderNo) {
        // 获取当前请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String tokenType = (String) request.getAttribute("tokenType");
        
        // 验证是否是商家token
        if (!"merchant".equals(tokenType)) {
            throw new BusinessException("无权限操作，请使用商家账号登录");
        }
        
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        
        // 验证商家ID是否匹配
        Long tokenMerchantId = (Long) request.getAttribute("merchantId");
        if (!order.getMerchantId().equals(tokenMerchantId)) {
            throw new BusinessException("无权操作其他商家的订单");
        }
        
        if (order.getStatus() != 1) {
            throw new BusinessException("订单状态不正确，无法接单");
        }
        
        order.setStatus(2); // 已接单配送中
        // 设置预计送达时间，假设为当前时间后30分钟
        order.setExpectedDeliveryTime(LocalDateTime.now().plusMinutes(30));
        
        Order savedOrder = orderRepository.save(order);
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(savedOrder.getId(), 0);
        
        return convertToOrderVO(savedOrder, orderItems);
    }

    /**
     * 完成订单
     * @param orderNo 订单号
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderVO completeOrder(String orderNo) {
        // 获取当前请求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String tokenType = (String) request.getAttribute("tokenType");
        
        // 验证是否是商家token
        if (!"merchant".equals(tokenType)) {
            throw new BusinessException("无权限操作，请使用商家账号登录");
        }
        
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        
        // 验证商家ID是否匹配
        Long tokenMerchantId = (Long) request.getAttribute("merchantId");
        if (!order.getMerchantId().equals(tokenMerchantId)) {
            throw new BusinessException("无权操作其他商家的订单");
        }
        
        if (order.getStatus() != 2) {
            throw new BusinessException("订单状态不正确，无法完成订单");
        }
        
        order.setStatus(3); // 已完成
        order.setActualDeliveryTime(LocalDateTime.now());
        
        Order savedOrder = orderRepository.save(order);
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(savedOrder.getId(), 0);
        
        return convertToOrderVO(savedOrder, orderItems);
    }

    /**
     * 取消订单
     * @param orderNo 订单号
     * @return 订单信息
     */
    @Override
    @Transactional
    public OrderVO cancelOrder(String orderNo) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        
        if (order.getStatus() > 1) {
            throw new BusinessException("订单已接单或已完成，无法取消");
        }
        
        order.setStatus(4); // 已取消
        
        Order savedOrder = orderRepository.save(order);
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(savedOrder.getId(), 0);
        
        return convertToOrderVO(savedOrder, orderItems);
    }

    /**
     * 删除订单
     * @param id 订单ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public Boolean deleteOrder(Long id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new BusinessException("订单不存在"));
        
        // 逻辑删除
        order.setIsDeleted(1);
        orderRepository.save(order);
        
        // 删除订单项
        List<OrderItem> orderItems = orderItemRepository.findByOrderIdAndIsDeleted(id, 0);
        for (OrderItem orderItem : orderItems) {
            orderItem.setIsDeleted(1);
            orderItemRepository.save(orderItem);
        }
        
        return true;
    }

    /**
     * 生成订单号
     * @return 订单号
     */
    private String generateOrderNo() {
        // 生成订单号，格式：年月日时分秒+6位随机数
        String dateStr = LocalDateTime.now().toString().replaceAll("[^0-9]", "").substring(0, 14);
        String randomStr = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        return dateStr + randomStr;
    }

    /**
     * 转换为订单VO
     * @param order 订单
     * @param orderItems 订单项
     * @return 订单VO
     */
    private OrderVO convertToOrderVO(Order order, List<OrderItem> orderItems) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        
        // 调用用户服务获取用户名称
        Result<UserVO> userResult = userClient.getUserById(order.getUserId());
        if (userResult.getCode().equals(200) && userResult.getData() != null) {
            orderVO.setUserName(userResult.getData().getUsername());
        } else {
            orderVO.setUserName("未知用户");
        }
        
        // 调用商家服务获取商家名称
        Result<MerchantVO> merchantResult = merchantClient.getMerchantById(order.getMerchantId());
        if (merchantResult.getCode().equals(200) && merchantResult.getData() != null) {
            orderVO.setMerchantName(merchantResult.getData().getName());
        } else {
            orderVO.setMerchantName("未知商家");
        }
        
        // 设置订单状态描述
        String statusDesc = switch (order.getStatus()) {
            case 0 -> "待支付";
            case 1 -> "已支付待接单";
            case 2 -> "已接单配送中";
            case 3 -> "已完成";
            case 4 -> "已取消";
            default -> "未知状态";
        };
        orderVO.setStatusDesc(statusDesc);
        
        // 设置支付方式描述
        if (order.getPayMethod() != null) {
            String payMethodDesc = switch (order.getPayMethod()) {
                case 1 -> "微信";
                case 2 -> "支付宝";
                case 3 -> "余额";
                default -> "未知支付方式";
            };
            orderVO.setPayMethodDesc(payMethodDesc);
        }
        
        // 设置订单项
        List<OrderItemVO> orderItemVOList = orderItems.stream().map(item -> {
            OrderItemVO itemVO = new OrderItemVO();
            BeanUtils.copyProperties(item, itemVO);
            return itemVO;
        }).collect(Collectors.toList());
        orderVO.setOrderItems(orderItemVOList);
        
        return orderVO;
    }
} 